/*
 * 文 件 名:  ImageCompress.java
 * 版    权:  Huawei Technologies Co., Ltd. Copyright YYYY-YYYY,  All rights reserved
 * 描    述:  <描述>
 * 修 改 人:  lKF34018
 * 修改时间:  2012-7-31
 * 跟踪单号:  <跟踪单号>
 * 修改单号:  <修改单号>
 * 修改内容:  <修改内容>
 */
package com.kuanrf.common.tools;

import java.awt.Image;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;

import javax.imageio.ImageIO;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.im4java.core.ConvertCmd;
import org.im4java.core.GMOperation;
import org.im4java.core.IMOperation;

/**
    
 * 图片处理类：此类依赖GraphicsMagick第三方工具
 * 
 * @author  lKF34018
 * @version  [版本号, 2012-7-31]
 * @see  [相关类/方法]
 * @since  [产品/模块版本]
 */
public class ImageCompressTools
{
    /**
     * 日志记录器
     */
    private static final Log logger = LogFactory.getLog(ImageCompressTools.class);
    
    //    /**
    //     * 将图片按宽等比率缩放
    //     * <功能详细描述>
    //     * @param srcImg 原图片
    //     * @param outImg 压缩后图片
    //     * @param width 压缩图片宽
    //     * @return [参数说明]
    //     * 
    //     * @return String [返回类型说明]
    //     * @exception throws [违例类型] [违例说明]
    //     * @see [类、类#方法、类#成员]
    //     */
    //    public static String compressImage_new(File srcImg, File outImg,
    //            double width)
    //    {
    //        Image img = checkImageFile(srcImg);
    //        // 判断图片格式是否正确 
    //        if (img == null)
    //        {
    //            return null;
    //        }
    //        // 为等比缩放计算输出的图片宽度及高度 
    //        double rate = width / ((double) img.getWidth(null));
    //        //比例为百分比
    //        rate = rate * 100;
    //        //调用接口转换图片
    //        String result = compressImage(srcImg, outImg, rate);
    //        if (result != null)
    //        {
    //            return "ok";
    //        }
    //        else
    //        {
    //            return null;
    //        }
    //    }
    //    
    //    /**
    //     * 将图片按宽等比率缩放
    //     * <功能详细描述>
    //     * @param srcImg 原图片
    //     * @param outImg 压缩后图片
    //     * @param width 压缩图片宽
    //     * @return [参数说明]
    //     * 
    //     * @return String [返回类型说明]
    //     * @exception throws [违例类型] [违例说明]
    //     * @see [类、类#方法、类#成员]
    //     */
    //    public static String compressImage_new(File srcImg, File outImg,
    //            double width, double height, boolean isZoom)
    //    {
    //        Image img = checkImageFile(srcImg);
    //        if (img == null)
    //        {
    //            return null;
    //        }
    //        String result = null;
    //        int newWidth = 0;
    //        int newHeight = 0;
    //        int srcWidth = img.getWidth(null);
    //        int srcHeight = img.getHeight(null);
    //        //如果缩放
    //        if (isZoom)
    //        {
    //            // 为等比缩放计算输出的图片宽度及高度 
    //            double rate1 = width / ((double) img.getWidth(null));
    //            double rate2 = height / ((double) img.getHeight(null));
    //            // 根据缩放比率大的进行缩放控制 
    //            //double rate = rate1 > rate2 ? rate1 : rate2;
    //            //比例为百分比
    //            //rate = rate * 100;
    //            //按宽度压缩
    //            if (height == 0 || (width != 0 && rate1 < rate2))
    //            {
    //                if (srcWidth <= width)
    //                {
    //                    newWidth = srcWidth;
    //                    newHeight = srcHeight;
    //                }
    //                else
    //                {
    //                    newWidth = (int) width;
    //                    newHeight = (int) (srcHeight * rate1);
    //                }
    //            }
    //            // 按高度压缩
    //            else
    //            {
    //                if (srcHeight <= height)
    //                {
    //                    newWidth = srcWidth;
    //                    newHeight = srcHeight;
    //                }
    //                else
    //                {
    //                    newWidth = (int) (srcWidth * rate2);
    //                    newHeight = (int) height;
    //                }
    //            }
    //            //把Java图片处理方式改为使用GraphicsMagick处理
    //            String srcPath = srcImg.getAbsolutePath();
    //            String outPath = outImg.getAbsolutePath();
    //            try
    //            {
    //                result = cutImage(newWidth,
    //                        newHeight,
    //                        srcPath,
    //                        outPath,
    //                        1,
    //                        "80");
    //            }
    //            catch (Exception e)
    //            {
    //                result = null;
    //            }
    //        }
    //        else
    //        {
    //            if (width <= 0 || height <= 0)
    //            {
    //                return null;
    //            }
    //            newWidth = (int) width; // 输出的图片宽度 
    //            newHeight = (int) height; // 输出的图片高度 
    //            //把Java图片处理方式改为使用GraphicsMagick处理
    //            String srcPath = srcImg.getAbsolutePath();
    //            String outPath = outImg.getAbsolutePath();
    //            try
    //            {
    //                result = cutImage(newWidth,
    //                        newHeight,
    //                        srcPath,
    //                        outPath,
    //                        1,
    //                        "80");
    //            }
    //            catch (Exception e)
    //            {
    //                result = null;
    //            }
    //        }
    //        if (result != null)
    //        {
    //            return "ok";
    //        }
    //        else
    //        {
    //            return null;
    //        }
    //    }
    
    /**
     * 将图片按长宽或等比率缩放
     * <功能详细描述>
     * @param srcImg 原图片
     * @param outImg 压缩后图片
     * @param width 压缩图片宽(等比率时可为空)
     * @param height 输出的图片高度 (等比率时不能为空)
     * @param isZoom 是否等比开关(为true时根据缩放比率大的进行缩放控制 )
     * @param isOver 当新尺寸大于原图时，是否输出放大原图
     * @return 文件后缀名[参数说明]
     * 
     * @exception throws [违例类型] [违例说明]
     * @see [类、类#方法、类#成员]
     */
    public static String compressImage(File srcImg, File outImg, double width,
            double height, boolean isZoom, boolean isOver)
    {
        Image img = checkImageFile(srcImg);
        // 判断图片格式是否正确 
        if (img == null || outImg == null)
        {
            return null;
        }
        String srcPath = srcImg.getAbsolutePath();
        String newPath = outImg.getAbsolutePath();
        return compressImage(srcPath, newPath, width, height, isZoom, isOver);
        
    }
    
    /**
     * 将图片按长宽或等比率缩放
     * <功能详细描述>
     * @param srcPath 原图片
     * @param outPath 压缩后图片
     * @param width 压缩图片宽(等比率时不可为空)
     * @param height 输出的图片高度 (等比率时可为空)
     * @param isZoom 是否等比开关(为true时根据缩放比率大的进行缩放控制 )
     * @param isOver 当新尺寸大于原图时，是否输出放大原图
     * @return [参数说明]
     * 
     * @return String [返回类型说明]
     * @exception throws [违例类型] [违例说明]
     * @see [类、类#方法、类#成员]
     */
    public static String compressImage(String srcPath, String outPath,
            double width, double height, boolean isZoom, boolean isOver)
    {
        File srcImg = new File(srcPath);
        Image img = checkImageFile(srcImg);
        if (img == null)
        {
            return null;
        }
        String result = null;
        int newWidth = 0;
        int newHeight = 0;
        //原图大小
        int oWidth = img.getWidth(null);
        int oHeight = img.getHeight(null);
        //如果缩放
        if (isZoom)
        {
            try
            {
                //当新尺寸大于原图时，输出放大原图，按参数转换
                if (isOver)
                {
                    // 为等比缩放计算输出的图片宽度及高度 
                    double rate1 = width / oWidth;
                    double rate2 = height / oHeight;
                    // 根据缩放比率小的进行缩放控制 
                    double rate = rate1 > rate2 ? rate2 : rate1;
                    //比例为百分比
                    rate = rate * 100;
                    //调用接口转换图片
                    result = cutImage((int) rate,
                            (int) rate,
                            srcPath,
                            outPath,
                            2,
                            "80");
                }
                //当新尺寸大于原图时，保留原尺寸
                else
                {
                    newWidth = (int) width; // 输出的图片宽度
                    if (newWidth > oWidth)
                    {
                        newWidth = oWidth;
                    }
                    newHeight = (newWidth * oHeight) / oWidth;
                    //调用接口转换图片
                    
                    result = cutImage((int) newWidth,
                            (int) newHeight,
                            srcPath,
                            outPath,
                            1,
                            "80");
                }
            }
            catch (Exception e)
            {
                result = null;
            }
        }
        //不缩放，直接按参数输出新尺寸图片
        else
        {
            if (width <= 0 || height <= 0)
            {
                return null;
            }
            //当新尺寸大于原图时，保留原尺寸
            if (!isOver)
            {
                if (width > oWidth || height > oHeight)
                {
                    try
                    {
                        FileTools.copyFile(srcPath, outPath);
                        return "OK";
                    }
                    catch (IOException e)
                    {
                        result = null;
                    }
                }
            }
            newWidth = (int) width; // 输出的图片宽度 
            newHeight = (int) height; // 输出的图片高度
            //把Java图片处理方式改为使用GraphicsMagick处理
            try
            {
                result = cutImage(newWidth,
                        newHeight,
                        srcPath,
                        outPath,
                        1,
                        "80");
            }
            catch (Exception e)
            {
                result = null;
            }
            
        }
        if (result != null)
        {
            return "ok";
        }
        else
        {
            return null;
        }
    }
    
    /**
     * 将图片按等比率缩放
     * <功能详细描述>
     * @param srcDir 原图片所在目录
     * @param srcName 原图片名称
     * @param outDir 压缩后图片所在目录
     * @param outName 压缩后图片名称
     * @param isZoom 是否等比开关(为true时根据缩放比率大的进行缩放控制 )
     * @return [参数说明]
     * 
     * @return String [返回类型说明]
     * @exception throws [违例类型] [违例说明]
     * @see [类、类#方法、类#成员]
     */
    public static String compressImage(String srcDir, String srcName,
            String outDir, String outName, double width, double height,
            boolean isZoom)
    {
        if (isNullOrNone(srcDir) || isNullOrNone(srcName)
                || isNullOrNone(outDir) || isNullOrNone(outName))
        {
            return null;
        }
        String srcPath;//输入图片完整路径
        String outPath;//输出图片完成路径
        String separator = System.getProperty("file.separator");//操作系统路径分隔符
        //组合输入图片完整路径
        if (srcDir.endsWith(separator))
        {
            srcPath = srcDir + srcName;
        }
        else
        {
            srcPath = srcDir + separator + srcName;
        }
        //组合输出图片完成路径
        if (outDir.endsWith(separator))
        {
            outPath = outDir + outName;
        }
        else
        {
            outPath = outDir + separator + outName;
        }
        return compressImage(srcPath, outPath, width, height, isZoom, false);
    }
    
    /**
     * 将图片按等比率缩放
     * <功能详细描述>
     * @param srcImg 原图片
     * @param outImg 压缩后图片
     * @param zoomRate 缩放比率(百分制，如按原图80%缩放则输入80即可)
     * @return [参数说明]
     * 
     * @return String [返回类型说明]
     * @exception throws [违例类型] [违例说明]
     * @see [类、类#方法、类#成员]
     */
    public static String compressImage(File srcImg, File outImg, double zoomRate)
    {
        
        //输出图片大小不能为0
        if (srcImg == null || outImg == null || zoomRate <= 0)
        {
            return null;
        }
        
        try
        {
            if (!srcImg.exists())
            {
                return null;
            }
            //把Java图片处理方式改为使用GraphicsMagick处理
            String srcPath = srcImg.getAbsolutePath();
            String newPath = outImg.getAbsolutePath();
            cutImage((int) zoomRate, (int) zoomRate, srcPath, newPath, 2, "80");
        }
        catch (Exception ex)
        {
            return null;
        }
        return "ok";
        //原Java处理方式
        //        Image img = checkImageFile(srcImg);
        //        if (img == null)
        //        {
        //            return null;
        //        }
        //        int newWidth;
        //        int newHeight;
        //        
        //        // 为等比缩放计算输出的图片宽度及高度 
        //        double rate = zoomRate / 100;
        //        // 根据缩放比率大的进行缩放控制 
        //        newWidth = (int) (((double) img.getWidth(null)) * rate);
        //        newHeight = (int) (((double) img.getHeight(null)) * rate);
        //        return compressImage(srcImg, outImg, newWidth, newHeight);
    }
    
    /**
     * 将图片按等比率硬缩放
     * <功能详细描述>
     * @param srcPath 原图片完整路径
     * @param outPath 压缩后图片完成路径
     * @param zoomRate 缩放比率(百分制，如按原图80%缩放则输入80即可)
     * @return [参数说明]
     * 
     * @return String [返回类型说明]
     * @exception throws [违例类型] [违例说明]
     * @see [类、类#方法、类#成员]
     */
    public static String compressImage(String srcPath, String outPath,
            double zoomRate)
    {
        
        File srcImg = new File(srcPath);
        //File outImg = new File(outPath);
        Image img = checkImageFile(srcImg);
        if (img == null)
        {
            return null;
        }
        //等比例缩放
        try
        {
            cutImage((int) zoomRate, (int) zoomRate, srcPath, outPath, 2, "80");
        }
        catch (Exception e)
        {
            return null;
        }
        return "ok";
        //        int newWidth;
        //        int newHeight;
        //        
        //        // 为等比缩放计算输出的图片宽度及高度 
        //        double rate = zoomRate / 100;
        //        // 根据缩放比率大的进行缩放控制 
        //        newWidth = (int) (((double) img.getWidth(null)) * rate);
        //        newHeight = (int) (((double) img.getHeight(null)) * rate);
        //        return compressImage(srcImg, outImg, newWidth, newHeight);
    }
    
    /**
     * 将图片按等比率缩放
     * <功能详细描述>
     * @param srcDir 原图片所在目录
     * @param srcName 原图片名称
     * @param outDir 压缩后图片所在目录
     * @param outName 压缩后图片名称
     * @param zoomRate 缩放比率(百分制，如按原图80%缩放则输入80即可)
     * @return [参数说明]
     * 
     * @return String [返回类型说明]
     * @exception throws [违例类型] [违例说明]
     * @see [类、类#方法、类#成员]
     */
    public static String compressImage(String srcDir, String srcName,
            String outDir, String outName, double zoomRate)
    {
        if (isNullOrNone(srcDir) || isNullOrNone(srcName)
                || isNullOrNone(outDir) || isNullOrNone(outName))
        {
            return null;
        }
        String srcPath;//输入图片完整路径
        String outPath;//输出图片完成路径
        String separator = System.getProperty("file.separator");//操作系统路径分隔符
        //组合输入图片完整路径
        if (srcDir.endsWith(separator))
        {
            srcPath = srcDir + srcName;
        }
        else
        {
            srcPath = srcDir + separator + srcName;
        }
        //组合输出图片完成路径
        if (outDir.endsWith(separator))
        {
            outPath = outDir + outName;
        }
        else
        {
            outPath = outDir + separator + outName;
        }
        return compressImage(srcPath, outPath, zoomRate);
    }
    
    /**
     * 将图片按长宽缩放
     * <功能详细描述>
     * @param srcImg 原图片
     * @param outImg 压缩后图片
     * @param width 输出的图片宽度 
     * @param height 输出的图片高度 
     * @return [参数说明]
     * 
     * @return String [返回类型说明]
     * @exception throws [违例类型] [违例说明]
     * @see [类、类#方法、类#成员]
     */
    public static String compressImage(File srcImg, File outImg, int width,
            int height)
    {
        //输出图片大小不能为0
        if (width == 0 || height == 0)
        {
            return null;
        }
        
        try
        {
            if (srcImg == null || !srcImg.exists())
            {
                return null;
            }
            if (outImg == null)
            {
                return null;
            }
            //把Java图片处理方式改为使用GraphicsMagick处理
            
            String srcPath = srcImg.getAbsolutePath();
            String newPath = outImg.getAbsolutePath();
            cutImage(width, height, srcPath, newPath, 1, "80");
            
            //原Java处理方式
            
            //                BufferedImage tag = new BufferedImage(width, height,
            //                        BufferedImage.TYPE_INT_RGB);
            //                /*
            //                 * Image.SCALE_SMOOTH 的缩略算法 生成缩略图片的平滑度的
            //                 * 优先级比速度高 生成的图片质量比较好 但速度慢
            //                 */
            //                tag.getGraphics().drawImage(img.getScaledInstance(width,
            //                        height,
            //                        Image.SCALE_SMOOTH),
            //                        0,
            //                        0,
            //                        null);
            //                FileOutputStream out = new FileOutputStream(outImg);
            //                // JPEGImageEncoder可适用于其他图片类型的转换 
            //                JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(out);
            //                encoder.encode(tag);
            //                out.close();
        }
        catch (Exception ex)
        {
            return null;
        }
        return "ok";
    }
    
    /**
     * 检查图片文件是否有效
     * <功能详细描述>
     * @param imgFile
     * @return [参数说明]
     * 
     * @return Image [返回类型说明]
     * @exception throws [违例类型] [违例说明]
     * @see [类、类#方法、类#成员]
     */
    private static Image checkImageFile(File imgFile)
    {
        
        //获得源文件 
        if (imgFile == null || !imgFile.exists())
        {
            return null;
        }
        BufferedImage img = null;
        try
        {
            img = ImageIO.read(imgFile);
        }
        catch (IOException e)
        {
            return null;
        }
        // 判断图片格式是否正确 
        if (img == null || img.getWidth(null) == -1)
        {
            return null;
        }
        else
        {
            return img;
        }
    }
    
    /**
     * Description:判断字段空null <br>
     *
     * @param s
     * @return boolean
     */
    private static boolean isNullOrNone(String s)
    {
        if (s == null || "".equals(s.trim()))
        {
            return true;
        }
        
        return false;
    }
    
    /** * 根据坐标裁剪图片
     * @param srcPath 要裁剪图片的路径 
     * @param newPath 裁剪图片后的路径 
     * @param x 起始横坐标 
     * @param y 起始挫坐标 
     * @param x1 结束横坐标 
     * @param y1 结束挫坐标 
     */
    public static void cutImage(String srcPath, String newPath, int x, int y,
            int x1, int y1) throws Exception
    {
        int width = x1 - x;
        int height = y1 - y;
        GMOperation op = new GMOperation();
        //源图片
        op.addImage(srcPath);
        /**
         * width：裁剪的宽度 
         * height：裁剪的高度 
         * x：裁剪的横坐标 
         * y：裁剪的挫坐标 
         */
        op.crop(width, height, x, y);
        op.quality(80.0);
        //输出图片
        op.addImage(newPath);
        ConvertCmd convert = new ConvertCmd(true);
        convert.run(op);
        logger.info("执行的命令：" + convert.getCommand());
        logger.error("执行输出的错误日志：" + convert.getErrorText());
    }
    
    /** 
     * 根据尺寸缩放图片 
     * @param width 缩放后的图片宽度 
     * @param height 缩放后的图片高度 
     * @param srcPath 源图片路径 
     * @param newPath 缩放后图片的路径 
     * @param type 1为大小处理，2为比例处理，如（1 大小：1024x1024, 2 比例：50%x50%）
     * @param quality 图片质量（百分比,如90%则输入90即可）
     * @return 生成后的文件路径
     */
    public static String cutImage(int width, int height, String srcPath,
            String newPath, int type, String quality) throws Exception
    {
        IMOperation op = new IMOperation();
        ConvertCmd cmd = new ConvertCmd(true);
        //预留输入
        op.addImage(srcPath);
        //按大小缩放后并居中裁剪
        if (type == 1)
        {
            //按像素
            op.resize(width, height, '^');
            op.gravity("center");
            op.extent(width, height);
        }
        else
        {
            //按像素百分比
            String raw = width + "%x" + height + "%";
            //如果裁剪，则居中裁剪
            op.gravity("center");
            op.addRawArgs("-thumbnail", raw);
        }
        if ((quality != null && quality.equals("")))
        {
            op.addRawArgs("-quality", quality);
        }
        
        //预留输出
        op.addImage(newPath);
        cmd.run(op);
        
        logger.info("执行的命令：" + cmd.getCommand());
        logger.error("执行输出的错误日志：" + cmd.getErrorText());
        return newPath;
    }
    
    /** 
     * 给图片加水印，目前没有相关字体，请勿使用
     * @param srcPath 源图片路径 
     */
    //    public static void addImgText(String srcPath) throws Exception
    //    {
    //        GMOperation op = new GMOperation();
    //        op.font("宋体")
    //                .gravity("southeast")
    //                .pointsize(18)
    //                .fill("#BCBFC8")
    //                .draw("这是一个水印");
    //        op.addImage();
    //        op.addImage();
    //        ConvertCmd convert = new ConvertCmd(true);
    //        //             //linux下不要设置此值，不然会报错
    //        //             convert.setSearchPath("C:\\Program Files\\GraphicsMagick-1.3.17-Q16");
    //        convert.run(op, srcPath, srcPath);
    //    }
    
    /**
     * compressPic(大图片路径,生成小图片路径,大图片文件名,生成小图片文名,生成小图片宽度,生成小图片高度,是否等比缩放(默认为true))
     */
    public static void main(String[] arg) throws Exception
    {
        //cutImage("D:\\apple870.jpg", "D:\\apple870eee.jpg",98, 48, 370, 320); 
        Long start = System.currentTimeMillis();
        String result = null;
        
        //        cutImage(50,
        //                50,
        //                "F:\\temp\\欣奇典-03.jpg",
        //                "F:\\temp\\欣奇典-031.jpg",
        //                2,
        //                "80");
        
        File f1 = new File(
                "D:\\我的文档\\常用图片\\小图\\356337f1e5c70b33eba80b939c00a63c-33.jpg");
        //File f2 = new File("F:\\temp\\欣奇典-031.jpg");
        File f3 = new File(
                "D:\\我的文档\\常用图片\\小图\\356337f1e5c70b33eba80b939c00a63c-331.jpg");
        //        result = compressImage(f1, f2, 100, 100, true);
        //        System.out.println(result);
        result = compressImage(f1, f3, 400, 500, false, true);
        
        System.out.println(result);
        
        //        addImgText("F:\\temp\\afdafd.jpg");
        Long end = System.currentTimeMillis();
        System.out.println("time:" + (end - start));
    }
    
}
